﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web;
using Nop.Core;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping;
using Nop.Plugin.Payments.PayPalHosted.Helpers;
using Nop.Plugin.Payments.PayPalHosted.PayPalAPI;
using Nop.Services.Logging;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Tax;

namespace Nop.Plugin.Payments.PayPalHosted.Services
{
    public class PayPalHostedService : IPayPalHostedService
    {
        private readonly PayPalHostedPaymentSettings _payPalHostedPaymentSettings;
        private readonly IPayPalInterfaceService _payPalInterfaceService;
        private readonly IPayPalRequestService _payPalRequestService;
        private readonly IOrderService _orderService;
        private readonly ILogger _logger;
        private readonly IOrderProcessingService _orderProcessingService;

        public PayPalHostedService(PayPalHostedPaymentSettings payPalHostedPaymentSettings,
                                   IPayPalInterfaceService payPalInterfaceService,
                                   IPayPalRequestService payPalRequestService,
                                   IOrderService orderService,
                                   ILogger logger,
                                   IOrderProcessingService orderProcessingService)
        {
            _payPalHostedPaymentSettings = payPalHostedPaymentSettings;
            _payPalInterfaceService = payPalInterfaceService;
            _payPalRequestService = payPalRequestService;
            _orderService = orderService;
            _logger = logger;
            _orderProcessingService = orderProcessingService;
        }

        /// <summary>
        /// Gets Paypal URL
        /// </summary>
        /// <returns></returns>
        private string GetPaypalUrl()
        {
            return _payPalHostedPaymentSettings.IsLive ? "https://securepayments.paypal.com/cgi-bin/acquiringweb" :
                       "https://securepayments.sandbox.paypal.com/acquiringweb";
        }
        public BMCreateButtonResponseType GetButton(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            using (var payPalApiInterfaceClient = _payPalInterfaceService.GetService())
            {
                var customSecurityHeaderType = _payPalInterfaceService.GetRequesterCredentials();
                var button = payPalApiInterfaceClient
                    .BMCreateButton(ref customSecurityHeaderType,
                                    _payPalRequestService.GetBMCreateButtonRequest(postProcessPaymentRequest.Order));

                return button;
            }


        }

        public int HandlePayment(Dictionary<string, string> values)
        {

            string orderNumber = string.Empty;
            values.TryGetValue("custom", out orderNumber);
            Guid orderNumberGuid = Guid.Empty;
            try
            {
                orderNumberGuid = new Guid(orderNumber);
            }
            catch { }
            Order order = _orderService.GetOrderByGuid(orderNumberGuid);
            if (order != null)
            {
                PayPalResponseHelper.LogResponse(new PayPalFormData(values), order.OrderGuid);
                decimal total = decimal.Zero;
                try
                {
                    total = decimal.Parse(values["mc_gross"], new CultureInfo("en-US"));
                }
                catch (Exception exc)
                {
                    _logger.Error("PayPal Hosted. Error getting mc_gross", exc);
                }

                string payer_status = string.Empty;
                values.TryGetValue("payer_status", out payer_status);
                string payment_status = string.Empty;
                values.TryGetValue("payment_status", out payment_status);
                string pending_reason = string.Empty;
                values.TryGetValue("pending_reason", out pending_reason);
                string mc_currency = string.Empty;
                values.TryGetValue("mc_currency", out mc_currency);
                string txn_id = string.Empty;
                values.TryGetValue("txn_id", out txn_id);
                string payment_type = string.Empty;
                values.TryGetValue("payment_type", out payment_type);
                string payer_id = string.Empty;
                values.TryGetValue("payer_id", out payer_id);
                string receiver_id = string.Empty;
                values.TryGetValue("receiver_id", out receiver_id);
                string invoice = string.Empty;
                values.TryGetValue("invoice", out invoice);
                string payment_fee = string.Empty;
                values.TryGetValue("payment_fee", out payment_fee);

                var sb = new StringBuilder();
                sb.AppendLine("Paypal Response:");
                sb.AppendLine("total: " + total);
                sb.AppendLine("Payer status: " + payer_status);
                sb.AppendLine("Payment status: " + payment_status);
                sb.AppendLine("Pending reason: " + pending_reason);
                sb.AppendLine("mc_currency: " + mc_currency);
                sb.AppendLine("txn_id: " + txn_id);
                sb.AppendLine("payment_type: " + payment_type);
                sb.AppendLine("payer_id: " + payer_id);
                sb.AppendLine("receiver_id: " + receiver_id);
                sb.AppendLine("invoice: " + invoice);
                sb.AppendLine("payment_fee: " + payment_fee);


                //order note
                order.OrderNotes.Add(new OrderNote()
                {
                    Note = sb.ToString(),
                    DisplayToCustomer = false,
                    CreatedOnUtc = DateTime.UtcNow
                });
                _orderService.UpdateOrder(order);


                //mark order as paid
                if (_orderProcessingService.CanMarkOrderAsPaid(order))
                {
                    order.AuthorizationTransactionId = txn_id;
                    _orderService.UpdateOrder(order);

                    _orderProcessingService.MarkOrderAsPaid(order);
                }
            }

            return order.Id;
        }
    }

    public class PayPalFormData : Dictionary<string, string>
    {
        public PayPalFormData(Dictionary<string, string> values)
        {
            foreach (var value in values)
            {
                Add(value.Key, value.Value);
            }
        }
    }
}